大概兩個禮拜前我們已經有用 requests + BeautifulSoup 兩個套件來把文章爬取下來了,今天會把相關的邏輯都移植到 Scrapy 框架中。先附上完整程式碼,接著會有相關的說明。
Scrapy 也支援 CSS 和 XPath 選擇器,分別對應回應實例的 css(query) 方法和 xpath(query) 方法。
如果要取得純文字或屬性內容,對應的選擇器如下:
| 說明 | CSS | XPath | 
|---|---|---|
| 純文字 | .css('::text') | .xpath('text()') | 
| 屬性 | .css('::attr(attr-name)') | .xpath('@attr-name') | 
7 行,因為 iT 邦幫忙的網域 ithelp.ithome.com.tw 是子網域,所以這邊改成允許 ithome.com.tw 就可以了。
allowed_domains = ['ithome.com.tw']
9~11 行,因為我們是以網址帶參數的方式換頁,這邊就不使用 start_urls 這個屬性,改成覆寫 start_requests() 方法,用每一頁的網址來發送請求,並指定使用 parse(response) 方法來處理回應。
昨天有講到
start_requests()和parse(response)方法都必須回傳可迭代的(iterable)請求或爬取到的項目實例,所以都是用 yield 來回傳。
def start_requests(self):
    for page in range(1, 11):
        yield scrapy.Request(url=f'https://ithelp.ithome.com.tw/articles?tab=tech&page={page}', callback=self.parse)
13~24 行,處理列表頁回應的方法,邏輯跟之前一樣。比較特別的是在 24 行用了 response.follow() 方法來取得文章的請求,同時指定使用 parse_article(response) 發訪來處理文章的回應。
Scrapy 提供了 response.urljoin(url) 和 response.follow(url) 兩個方法來方便處理相對路徑,前者只會回傳一個對應的絕對路徑,後者則會回傳使用對應絕對路徑的請求。
yield response.follow(article_url, callback=self.parse_article)
26~65 行,處理文章回應的方法,邏輯也是跟之前幾乎相同就不多做說明了。注意在 65 行我們一樣用 yield 回傳爬取到的項目。
爬蟲名稱是 ithome,所以可以直接執行 scrapy crawl ithome 來啟動爬蟲。

可以在 console 中看到我們抓到的文章,如果要將結果儲存成 JSON 檔案,可以在執行時多加一個參數 scrapy crawl ithome -o ithome.json 或 scrapy crawl ithome -o ithome.csv,就可以在專案目錄中看到我們爬取到的結果存成 ithome.json 檔案了。